package com.yanqu.road.logic.activity.chuhan;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.logic.activity.tongbing.entiety.TongBingMapRoute;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ChuHanMapLogic {

    /**
     * 地图数据，找客户端要
     */
    public static String MAP_PARAM = "{\"cityLink\":[\"10001_10002\",\"10001_10027\",\"10002_10003\",\"10003_10004\",\"10004_10005\",\"10005_10006\",\"10005_10024\",\"10006_10007\",\"10007_10008\",\"10007_10169\",\"10008_10009\",\"10009_10010\",\"10009_10012\",\"10009_10013\",\"10010_10011\",\"10011_10012\",\"10013_10014\",\"10014_10015\",\"10014_10170\",\"10015_10016\",\"10016_10018\",\"10017_10018\",\"10018_10019\",\"10018_10067\",\"10019_10020\",\"10020_10021\",\"10020_10035\",\"10021_10022\",\"10022_10023\",\"10022_10033\",\"10023_10024\",\"10023_10033\",\"10024_10025\",\"10025_10026\",\"10026_10027\",\"10027_10028\",\"10028_10029\",\"10028_10046\",\"10029_10030\",\"10029_10031\",\"10029_10044\",\"10030_10031\",\"10031_10032\",\"10032_10033\",\"10032_10042\",\"10033_10034\",\"10034_10035\",\"10035_10036\",\"10035_10042\",\"10036_10037\",\"10036_10041\",\"10037_10038\",\"10038_10039\",\"10038_10065\",\"10039_10040\",\"10039_10055\",\"10039_10063\",\"10040_10041\",\"10040_10054\",\"10041_10042\",\"10041_10053\",\"10042_10043\",\"10043_10044\",\"10044_10045\",\"10044_10052\",\"10045_10046\",\"10046_10047\",\"10047_10048\",\"10048_10049\",\"10048_10167\",\"10049_10050\",\"10049_10057\",\"10050_10051\",\"10050_10056\",\"10051_10052\",\"10051_10054\",\"10052_10053\",\"10053_10054\",\"10054_10055\",\"10056_10060\",\"10057_10058\",\"10057_10059\",\"10059_10060\",\"10059_10061\",\"10060_10062\",\"10061_10062\",\"10061_10168\",\"10062_10063\",\"10063_10064\",\"10064_10065\",\"10065_10066\",\"10066_10067\"],\"event\":[0,0,0]}";

    // =============================

    /**
     * 生成地图
     *
     * @return 地点，相邻地点List
     */
    public static ChuHanMapGraph getMapGraph() {
        ChuHanMapGraph graph = new ChuHanMapGraph();
        String mapParam = MAP_PARAM;
        Map<Integer, List<Integer>> listMap = new ConcurrentHashMap<>();

        JSONObject jsonObject = JSONObject.parseObject(mapParam);
        JSONArray cityLink = jsonObject.getJSONArray("cityLink");
        for (Object o : cityLink) {
            String s = String.valueOf(o);
            List<Integer> list = StringUtils.stringToIntegerList(s, "_");
            int cityA = list.get(0);
            int cityB = list.get(1);

            graph.addEdge(cityA, cityB);
        }

        return graph;
    }

    /**
     * 生成NPC事件位置
     */
    public static int getNpcEventPosNumConfig() {
        String mapParam = MAP_PARAM;
        JSONObject jsonObject = JSONObject.parseObject(mapParam);
        JSONArray event = jsonObject.getJSONArray("event");
        return (int) event.get(0);
    }

    // =============================

    /**
     * 自动寻路
     *
     * @param canMoveRouteMap     过滤了无法移动的点的地图
     * @param battlefieldRouteMap 处于战斗状态的点的地图
     * @param from                出发城市
     * @param to                  到达城市
     * @return 路径，含起点终点，null表示无通路
     */
    public static List<Integer> getRouteList(Map<Integer, ChuHanMapNode> canMoveRouteMap, Map<Integer, ChuHanMapNode> battlefieldRouteMap, int from, int to) {
        // 优先寻路没交战的路线
        List<Integer> routeList = getRouteList(canMoveRouteMap, from, to);
        if (routeList == null || routeList.size() <= 1) {
            // 没交战的路线寻不到则加入有战斗的城池路线
            canMoveRouteMap.putAll(battlefieldRouteMap);
            routeList = getRouteList(canMoveRouteMap, from, to);
        }
        return routeList;
    }

    /**
     * 自动寻路
     *
     * @param canMoveRouteMap 过滤了无法移动的点的地图
     * @param from            出发城市
     * @param to              到达城市
     * @return 路径，含起点终点，null表示无通路
     */
    public static List<Integer> getRouteList(Map<Integer, ChuHanMapNode> canMoveRouteMap, int from, int to) {
        Map<Integer, TongBingMapRoute> movedMap = new HashMap<>();
        Queue<Integer> queue = new LinkedList<>();

        // 添加起点
        movedMap.put(from, new TongBingMapRoute(from, new ArrayList<>()));
        queue.offer(from);

        while (!queue.isEmpty()) {

            // 取当前点和新的路径
            Integer pos = queue.poll();
            TongBingMapRoute lastRoute = movedMap.get(pos);
            List<Integer> curRoute = new ArrayList<>(lastRoute.getRoute());
            curRoute.add(pos);

            // 遍历连接点
            ChuHanMapNode podNode = canMoveRouteMap.get(pos);
            Set<ChuHanMapNode> nextPosList = podNode.getAdjacent();
            if (podNode == null || podNode.getAdjacent().isEmpty()) {
                continue;
            }
            for (ChuHanMapNode nextPos : nextPosList) {

                // 找到终点
                if (nextPos.getCityId() == to) {
                    List<Integer> result = new ArrayList<>(curRoute);
                    result.add(to);
                    return result;
                }

                // 加队列等会儿继续找
                if (!movedMap.containsKey(nextPos.getCityId())) {
                    queue.offer(nextPos.getCityId());
                    movedMap.put(nextPos.getCityId(), new TongBingMapRoute(nextPos.getCityId(), curRoute));
                }
            }

        }

        // 没找到
        return null;
    }

    /**
     * 获取阵营中间城市地点
     */
    public static List<Integer> getMiddleCityId(ChuHanMapGraph graph, Set<Integer> camp1PosSet, Set<Integer> camp2PosSet) {
        Set<Integer> lastPosSet = new HashSet<>(); // 走过的点
        List<List<Integer>> lastResultList = new ArrayList<>(); // 多条路线

        Set<Integer> curPosSet = new HashSet<>();
        List<List<Integer>> curResultList = new ArrayList<>(); // 多条路线

        // 准备数据
        lastPosSet.addAll(camp1PosSet);
        for (Integer pos : camp1PosSet) {
            lastResultList.add(Collections.singletonList(pos));
        }

        // 处理
        for (int i = 0; i < 99999; i++) {

            // 找每条可以走的路走一格
            for (List<Integer> route : lastResultList) {
                Integer cityId = route.get(route.size() - 1);
                ChuHanMapNode node = graph.getNode(cityId);
                Set<ChuHanMapNode> linked = node.getAdjacent();
//                List<Integer> linked = graph.get(route.get(route.size() - 1));
                for (ChuHanMapNode linkedPos : linked) {
                    if (lastPosSet.contains(linkedPos.getCityId())) {
                        continue;
                    }
                    if (camp1PosSet.contains(linkedPos.getCityId())) {
                        continue;
                    }
                    ArrayList<Integer> newRoute = new ArrayList<>(route);
                    newRoute.add(linkedPos.getCityId());
                    curResultList.add(newRoute);
                    curPosSet.add(linkedPos.getCityId());
                }
            }

            // 无路可走
            if (curResultList.isEmpty()) {
                break;
            }

            // 看看有没有结果
            List<List<Integer>> finalResult = new ArrayList<>();
            for (List<Integer> route : curResultList) {
                if (camp2PosSet.contains(route.get(route.size() - 1))) {
                    finalResult.add(route);
                }
            }

            // 有结果返回
            if (!finalResult.isEmpty()) {

                List<Integer> list = new ArrayList<>();

                // 多个结果都要返回
                for (List<Integer> tmpList : finalResult) {

                    int posIndex = tmpList.size() / 2;
                    list.add(tmpList.get(posIndex)); // 中点

                    if (tmpList.size() % 2 == 0) { // 有两个中点
                        posIndex = posIndex - 1;
                        list.add(tmpList.get(posIndex));
                    }
                }

                return list;
            }

            // 没结果继续找
            lastPosSet = curPosSet;
            lastResultList = curResultList;
            curResultList = new ArrayList<>();
            curPosSet = lastPosSet;
        }

        // 容错返回
        System.err.println("出bug了啊啊啊啊啊啊啊getMiddleCityId");
        return new ArrayList<>(new Random().nextDouble() > 0.5 ? camp1PosSet : camp2PosSet);
    }

}
